﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace Orktane.Behaviors
{
    public class TextBoxPrefixBehavior 
        : Behavior<TextBox>
    {
        public static readonly DependencyProperty PrefixProperty =
            DependencyProperty.Register("ValueRelay", typeof(string), typeof(TextBoxPrefixBehavior),
            new PropertyMetadata(null, OnPrefixChanged));

#region Properties

        public string Prefix
        {
            get { return Convert.ToString(GetValue(PrefixProperty)); }
            set { SetValue(PrefixProperty, value); }
        }

#endregion

#region Overrides

        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.SelectionChanged += new RoutedEventHandler(AssociatedObject_SelectionChanged);
            this.AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
        }

        void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(Prefix) && string.IsNullOrEmpty(AssociatedObject.Text))
                this.AssociatedObject.Text = this.Prefix;
            this.AssociatedObject.Loaded -= new RoutedEventHandler(AssociatedObject_Loaded);
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.SelectionChanged -= new RoutedEventHandler(AssociatedObject_SelectionChanged);
        }

#endregion

#region Handlers

        private void AssociatedObject_SelectionChanged(object sender, RoutedEventArgs e)
        {
            // basic check
            if (string.IsNullOrEmpty(this.Prefix)) return;

            // if the length is less that 
            //if (this.AssociatedObject.Text.Length != 0 && this.AssociatedObject.Text.Length < this.Prefix.Length)
            //{
            //    this.AssociatedObject.Text = this.Prefix + this.AssociatedObject.Text.Substring(this.Prefix.Length - 1);
            //}
            // match each character of the prefix
            if (this.AssociatedObject.Text == null || !this.AssociatedObject.Text.StartsWith(this.Prefix))
            {
                var _text = this.AssociatedObject.Text ?? string.Empty;

                for (var _i = 0; _i < this.Prefix.Length; _i++)
                {
                    if ((_text.Length - 1) < _i)
                    {
                        _text += this.Prefix[_i].ToString();
                    }   
                    else if (_text[_i] != this.Prefix[_i])
                    {
                        _text = _text.Insert(_i, this.Prefix[_i].ToString());
                    }
                }

                this.AssociatedObject.Text = _text;
            }

            // update selection
            if (this.AssociatedObject.SelectionStart < this.Prefix.Length)
            {
                this.AssociatedObject.SelectionStart = this.Prefix.Length;
            }
        }

        private static void OnPrefixChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TextBoxPrefixBehavior)d).UpdatePrefix(Convert.ToString(e.OldValue), Convert.ToString(e.NewValue));
        }

#endregion

#region Helpers

        private void UpdatePrefix(string oldPrefix, string newPrefix)
        {
            if (this.AssociatedObject == null) return;
            if (!string.IsNullOrEmpty(oldPrefix) && this.AssociatedObject.Text.StartsWith(oldPrefix))
            {
                this.AssociatedObject.Text = this.AssociatedObject.Text.Substring(oldPrefix.Length);
            }
            if (!string.IsNullOrEmpty(newPrefix) && !this.AssociatedObject.Text.StartsWith(newPrefix))
            {
                this.AssociatedObject.Text = newPrefix + this.AssociatedObject.Text;
            }
            UpdateSelection(newPrefix);
        }

        private void UpdateSelection(string newPrefix)
        {
            if (this.AssociatedObject == null) return;
            this.AssociatedObject.SelectionStart = string.IsNullOrEmpty(newPrefix) ?  0 : newPrefix.Length;
        }

#endregion

    }
}